﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Altairis.Web.UI.WebControls {

    [ValidationProperty("Text")]
    public class DateTimeTextBox : CompositeControl, INamingContainer, ITextControl {
        private const string TIME_FORMAT_STRING = "HH:mm";
        private const string DEFAULT_MAX_TIME = "23:59";
        private const string DEFAULT_MIN_TIME = "00:00";
        private const string DEFAULT_DATE_FORMAT_STRING = "d";

        private TextBox dateControl;
        private DropDownList timeControl;

        public DateTimeTextBox() {
            this.MinTime = "00:00";
            this.MaxTime = "23:59";
            this.DateFormatString = "d";
            this.Granularity = TimeGranularity.HalfHour;
        }

        [CssClassProperty]
        public string DateCssClass {
            get { return (string)this.ViewState["DateCssClass"]; }
            set { this.ViewState["DateCssClass"] = value; }
        }

        [DefaultValue(DEFAULT_DATE_FORMAT_STRING)]
        public string DateFormatString {
            get { return (string)this.ViewState["DateFormatString"]; }
            set { this.ViewState["DateFormatString"] = value; }
        }

        public Unit DateWidth {
            get { return (Unit)this.ViewState["DateWidth"]; }
            set { this.ViewState["DateWidth"] = value; }
        }

        [DefaultValue(TimeGranularity.HalfHour)]
        public TimeGranularity Granularity {
            get { return (TimeGranularity)this.ViewState["Granularity"]; }
            set { this.ViewState["Granularity"] = value; }
        }

        [DefaultValue(DEFAULT_MAX_TIME)]
        public string MaxTime {
            get { return (string)this.ViewState["MaxTime"]; }
            set { this.ViewState["MaxTime"] = value; }
        }

        [DefaultValue(DEFAULT_MIN_TIME)]
        public string MinTime {
            get { return (string)this.ViewState["MinTime"]; }
            set { this.ViewState["MinTime"] = value; }
        }

        public string Text {
            get {
                if (!this.ChildControlsCreated || string.IsNullOrWhiteSpace(this.dateControl.Text)) return null;
                return this.dateControl.Text + " " + this.timeControl.SelectedValue;
            }
            set {
                this.EnsureChildControls();
                DateTime dt;
                if (!DateTime.TryParse(value, out dt)) throw new FormatException("Unrecognized DateTime format.");
                this.dateControl.Text = dt.ToString(this.DateFormatString);
                var li = this.timeControl.Items.FindByValue(dt.ToString(TIME_FORMAT_STRING));
                li.Selected = true;
            }
        }

        [CssClassProperty]
        public string TimeCssClass {
            get { return (string)this.ViewState["TimeCssClass"]; }
            set { this.ViewState["TimeCssClass"] = value; }
        }

        public Unit TimeWidth {
            get { return (Unit)this.ViewState["TimeWidth"]; }
            set { this.ViewState["TimeWidth"] = value; }
        }

        protected override void CreateChildControls() {
            base.Controls.Clear();

            this.dateControl = new TextBox {
                ID = "Date",
                Width = this.DateWidth,
                CssClass = this.DateCssClass
            };
            this.timeControl = new DropDownList {
                ID = "Time",
                Width = this.TimeWidth,
                CssClass = this.TimeCssClass
            };

            this.Controls.Add(this.dateControl);
            this.Controls.Add(this.timeControl);

            var minTime = DateTime.ParseExact(this.MinTime, TIME_FORMAT_STRING, CultureInfo.InvariantCulture).TimeOfDay;
            var maxTime = DateTime.ParseExact(this.MaxTime, TIME_FORMAT_STRING, CultureInfo.InvariantCulture).TimeOfDay;

            for (var m = minTime.TotalMinutes; m <= maxTime.TotalMinutes; m += (int)this.Granularity) {
                var t = new DateTime();
                t = t.AddMinutes(m);
                this.timeControl.Items.Add(new ListItem {
                    Text = t.ToString(TIME_FORMAT_STRING),
                    Value = t.ToString(TIME_FORMAT_STRING)
                });
            }

            this.ChildControlsCreated = true;
        }
    }
}